package com.notetool.util.tokenparser;

import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.PrintWriter;

import com.notetool.util.tokenparser.syntax.Model;

public class TokenList
{
	
    ////////////////////
    // Members
    private Token head;
    private Token tail;
    
    ////////////////////
    // Constructors
    public TokenList ()
    {
    	
    }
    
    ////////////////////
    // Accessors
    public Token getFirst ()
    {
    	return head;
    }
    
    public Token getLast ()
    {
    	return tail;
    }
    
    ////////////////////
    // Public methods
    public void add (Token token)
    {
    	if (token == null)
    	    return;
    	
    	// If we don't have a head, then this token becomes the new head
    	if (head == null)
    		head = token;
    	
    	// If we have a tail, we chain the token
    	if (tail != null)
    	    // Here we grab the result. The result is the object that represents the token we're adding. In most cases, the token we're passing as a parameter is returned. But if some special rules apply, another object may be returned, such as the token representing the first SingleCharToken of a streak of SingleCharToken's where only 1 token of that kind is allowed in a row.
    	    token = tail.link (token);
    	
    	// The token we just added (or its representation, see comment above) always becomes the new tail
    	tail = token;
    }
    
    public void purge (String cls)
    {
        if (cls == null)
            return;
        
        Token curTok = head;
        while (curTok != null)
        {
            Token next = curTok.getNext ();
            
            if (curTok.is (cls))
                remove (curTok);
            
            curTok = next;
        }
    }
    
    public void purge (Model model)
    {
        if (model == null)
            return;
        
        Token curTok = head;
        while (curTok != null)
        {
            Token next = curTok.getNext ();
            
            if (curTok.getModel () == model)
                remove (curTok);
            
            curTok = next;
        }
    }
    
    public void remove (Token token)
    {
        if (token == head)
            head = token.getNext ();
            
        if (token == tail)
            tail = token.getPrevious ();
            
        token.unLink ();
    }
    
    public void print (OutputStream out)
    {
        PrintWriter writer = new PrintWriter (out);
        
        writer.write("----------------------------------------------------------------------\n");
        writer.write("--                          TokenList dump                          --\n");
        writer.write("----------------------------------------------------------------------\n");
        
        Token curTok = head;
        while (curTok != null)
        {
            writer.write ("- " + curTok.getModel ().getClass () + "('" + curTok.toString () + "') ");
            writer.write ("[");
            String[] classes = curTok.getClasses ();
            for (int i = 0; i < classes.length; ++ i)
            {
                if (i > 0)
                    writer.write (", ");
                
                writer.write (classes[i]);
            }
            writer.write ("]\n");
            curTok = curTok.getNext ();
        }
        
        writer.write("----------------------------------------------------------------------\n");
        
        writer.flush ();
    }
	
}
